/**
 * Copyright (C) 2009 Marcel Urbanek
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.urbiworx.sugar;

import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;


public class SugarContentHandler extends org.xml.sax.helpers.DefaultHandler
{
	Locator locator;
	@Override
	public void setDocumentLocator(Locator locator) {
		this.locator=locator;
		super.setDocumentLocator(locator);
	}

	Logger logger=Logger.getLogger("de.urbiworx.sugar");

	private Map<String,SugarConfigurationEntry> configurationMap;
	private Map<String,SugarConfigurationEntry> configurationMapByView;
	private Map<String,SugarConfigurationEntry> configurationMapByClass;
	private List<SugarConfigurationEntry> configuration;
	private List<AdditionalModuleEntry> additionalModules;
	private String filename;
	public Map<String, SugarConfigurationEntry> getConfigurationMap() {
		return configurationMap;
	}
	
	public Map<String, SugarConfigurationEntry> getConfigurationMapByView() {
		return configurationMapByView;
	}
	
	public Map<String, SugarConfigurationEntry> getConfigurationMapByClass() {
		return configurationMapByClass;
	}

	public List<SugarConfigurationEntry> getConfiguration() {
		return configuration;
	}
	
	public SugarContentHandler(List <SugarConfigurationEntry>configuration,List<AdditionalModuleEntry> additionalModules,Map<String,SugarConfigurationEntry>configurationMap, Map<String,SugarConfigurationEntry>configurationMapByView, Map<String,SugarConfigurationEntry>configurationMapByClass, String filename)
	{
		this.additionalModules=additionalModules;
		this.configurationMapByClass=configurationMapByClass;
		this.configurationMapByView=configurationMapByView;
		this.configurationMap=configurationMap;
		this.configuration=configuration;
		this.filename=filename;
	}
	
	@Override
	public void startElement(String namespaceURI, String localName, String qName,
			Attributes atts) throws SAXException {
		//Only read the "bind" and "module" entries
		if ("module".equalsIgnoreCase(qName))
		{
			AdditionalModuleEntry entry=new AdditionalModuleEntry(atts,locator.getLineNumber(),filename);
			additionalModules.add(entry);
		}
		else if ("bind".equalsIgnoreCase(qName))
		{
			//Instantiate a new Entry, attribute handling is done in its constructor
			SugarConfigurationEntry entry=new SugarConfigurationEntry(atts,locator.getLineNumber(),filename);
			//One name should only be used once
			if ((entry.getView()!=null)&&(configurationMapByView.containsKey(entry.getView())))
			{
				SugarConfigurationEntry firstEntry=configurationMapByView.get(entry.getView());
				throw new SugarException("A view may only be associated once. First occurence:"+firstEntry.getFilename()+" Line:"+firstEntry.getLine()
						+" Second occurence:"+entry.getFilename()+" Line:"+entry.getLine());
			}

			if (entry.getName()!=null&&configurationMap.containsKey(entry.getName()))
			{
				logger.warning("Following name is defined twice in the sugar configuration:"+
						entry.getName()+", will use the first definition");
			}
			else
			{
				//Only if it has a name, put it in the map. The map is used for EL Resolving later on
				//Entries without name are of no use for the el resolving process
				if (entry.getName()!=null)
				{
					configurationMap.put(entry.getName(),entry);
				}
				else
				{
					configurationMapByClass.put(entry.getType(),entry);
				}
				if (entry.getView()!=null)
				{
					configurationMapByView.put(entry.getView(), entry);
				}
				//Add everything to the configuration list, this is given to guice later on
				configuration.add(entry);
			}
		} 
		else if (!("sugar-config".equalsIgnoreCase(qName)))
		{
			//No elements beside this three are supported
			logger.warning("Following configuration element is unknown:"+qName);
		}
		
	}


}
